package com.example.dakotanews.service.implement;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.dakotanews.dto.utils.ApiResponse;
import com.example.dakotanews.dto.utils.ResponseCode;
import com.example.dakotanews.dto.ChildCommentDTO;
import com.example.dakotanews.dto.CommentDTO;
import com.example.dakotanews.entity.comment.NewsChildComment;
import com.example.dakotanews.entity.comment.NewsComment;
import com.example.dakotanews.entity.relation.NewsChildCommentSupport;
import com.example.dakotanews.entity.relation.NewsCommentSupport;
import com.example.dakotanews.entity.User;
import com.example.dakotanews.mapper.UserMapper;
import com.example.dakotanews.mapper.comment.NewsChildCommentMapper;
import com.example.dakotanews.mapper.comment.NewsCommentMapper;
import com.example.dakotanews.mapper.relation.NewsChildCommentSupportMapper;
import com.example.dakotanews.mapper.relation.NewsCommentSupportMapper;
import com.example.dakotanews.service.CommentService;
import com.example.dakotanews.utils.TimeHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class CommentServiceImpl implements CommentService {

    private final NewsCommentMapper newsCommentMapper;
    private final NewsChildCommentMapper newsChildCommentMapper;
    private final UserMapper userMapper;
    private final NewsCommentSupportMapper newsCommentSupportMapper;
    private final NewsChildCommentSupportMapper newsChildCommentSupportMapper;
    private final TimeHandler timeHandler;

    @Autowired
    public CommentServiceImpl(
            NewsCommentMapper newsCommentMapper,
            NewsChildCommentMapper newsChildCommentMapper,
            UserMapper userMapper,
            NewsCommentSupportMapper newsCommentSupportMapper,
            NewsChildCommentSupportMapper newsChildCommentSupportMapper,
            TimeHandler timeHandler
    ) {
        this.newsCommentMapper = newsCommentMapper;
        this.newsChildCommentMapper = newsChildCommentMapper;
        this.userMapper = userMapper;
        this.newsCommentSupportMapper = newsCommentSupportMapper;
        this.newsChildCommentSupportMapper = newsChildCommentSupportMapper;
        this.timeHandler = timeHandler;
    }

    ApiResponse<Object> apiResponse;

    /**
     * @description 需要实现的业务：
     * 1、获取指定新闻下的所有一级评论
     * 2、对于每一条一级评论，获取评论信息，然后根据该一级评论的ID获取对应的所有二级评论，封装为一个List集合
     * 3、若访客用户已登录则额外获取一级评论和二级评论的操作标识符封装进去
     */
    @Override
    public ApiResponse<Object> getNewsAllComment(
            Integer newsId, Integer sortType, int page, int pageSize, Integer userId) {
        // 以下集合类型均用于让返回数据呈现为标准结构
        Map<String, Object> data = new HashMap<>();

        List<CommentDTO> newsComments = new ArrayList<>();

        // 查询记录总数，用于在前端做分页处理
        int allCommentNum = Math.toIntExact(newsCommentMapper.selectCount(new QueryWrapper<NewsComment>()
                .eq("news_id", newsId)));

        // 分页查询一级评论
        List<NewsComment> newsCommentList;
        Page<NewsComment> commentPage = new Page<>(page, pageSize);
        QueryWrapper<NewsComment> newsCommentQueryWrapper
                = new QueryWrapper<NewsComment>().eq("news_id", newsId);

        // 根据排序类型进行排序查询
        if (sortType == 0) {
            // 默认排序，按照id升序
            newsCommentQueryWrapper.orderByAsc("id");
        } else if (sortType == 1) {
            // 按照时间降序排序
            newsCommentQueryWrapper.orderByDesc("commit_time");
        } else {
            // 按照点赞数降序排序
            newsCommentQueryWrapper.orderByDesc("support_num");
        }
        newsCommentList = newsCommentMapper.selectPage(commentPage, newsCommentQueryWrapper).getRecords();


        if (newsCommentList.size() != 0) {
            // 将查询结果封装成标准结构。对每一条评论进行操作
            for (NewsComment newsComment : newsCommentList) {
                // 查询评论用户信息
                User user = userMapper.selectById(newsComment.getUserId());
                CommentDTO commentDTO = new CommentDTO(newsComment);
                commentDTO.setNickname(user.getNickname());
                commentDTO.setProfile(user.getProfile());
                commentDTO.setCommitTime(timeHandler.dateTimeConvert(newsComment.getCommitTime()));

                // 获取点赞状态，若为已登录用户
                if (userId != null) {
                    // 查询评论点赞关系表，若查询结果不为空，说明是已点赞状态
                    if (newsCommentSupportMapper.selectOne(new QueryWrapper<NewsCommentSupport>()
                            .eq("news_comment_id", newsComment.getId())
                            .eq("user_id", userId)) != null) {
                        commentDTO.setSupportIf(1);
                    } else {
                        commentDTO.setSupportIf(0);
                    }
                    data.put("isLogin", 1);
                } else {
                    data.put("isLogin", 0);
                }

                // 获取该评论下的所有子评论
                List<NewsChildComment> newsChildCommentList = newsChildCommentMapper.selectList(
                        new QueryWrapper<NewsChildComment>()
                                .eq("parent_id", newsComment.getId()));

                if (newsChildCommentList != null) {
                    List<ChildCommentDTO> childCommentDTOList = new ArrayList<>();
                    for (NewsChildComment newsChildComment : newsChildCommentList) {
                        // 查询子评论用户信息
                        User childUser = userMapper.selectById(newsChildComment.getUserId());
                        // 查询子评论中被回复的用户的用户信息
                        User repliedUser = userMapper.selectById(newsChildComment.getRepliedUserId());
                        ChildCommentDTO childCommentDTO = new ChildCommentDTO(newsChildComment);
                        childCommentDTO.setNickname(childUser.getNickname());
                        childCommentDTO.setProfile(childUser.getProfile());
                        childCommentDTO.setCommitTime(timeHandler.dateTimeConvert(newsChildComment.getCommitTime()));

                        if (repliedUser != null) {
                            childCommentDTO.setRepliedNickname(repliedUser.getNickname());
                        }
                        // 若为已登录用户
                        if (userId != null) {
                            if (newsChildCommentSupportMapper.selectOne(new QueryWrapper<NewsChildCommentSupport>()
                                    .eq("news_child_comment_id", newsChildComment.getId())
                                    .eq("user_id", userId)) != null) {
                                childCommentDTO.setSupportIf(1);
                            } else {
                                childCommentDTO.setSupportIf(0);
                            }
                        }
                        // 将封装好的通用子评论类添加到通用子评论List集合中
                        childCommentDTOList.add(childCommentDTO);
                    }
                    // 将封装好的通用子评论List集合赋值给当前的通用评论
                    commentDTO.setChildComments(childCommentDTOList);
                    commentDTO.setChildCommentNum(childCommentDTOList.size());
                }
                newsComments.add(commentDTO);
            }
            data.put("newsComments", newsComments);
            // 返回的是记录总数
            data.put("commentNum", allCommentNum);

            apiResponse = new ApiResponse<>(ResponseCode.SUCCESS, "获取评论列表成功", data);
        } else {
            apiResponse = new ApiResponse<>(ResponseCode.NOT_FOUND, "没有对应评论", null);
        }

        return apiResponse;
    }

    @Override
    public ApiResponse<Object> commitComment(Integer newsId, String comment, Integer userId) {
        // 新建新闻评论类并插入记录
        NewsComment newsComment = new NewsComment();
        newsComment.setNewsId(newsId);
        newsComment.setUserId(userId);
        newsComment.setComment(comment);
        newsCommentMapper.insert(newsComment);

        int commentId = newsComment.getId();

        apiResponse = new ApiResponse<>(ResponseCode.SUCCESS, "请求成功", commentId);
        return apiResponse;
    }

    @Override
    public ApiResponse<Object> commitChildComment(
            Integer newsId, Integer parentId, Integer repliedUserId, String comment, Integer userId) {
        // 新建新闻子评论类并插入记录
        NewsChildComment newsChildComment = new NewsChildComment();
        newsChildComment.setParentId(parentId);
        newsChildComment.setUserId(userId);
        newsChildComment.setRepliedUserId(repliedUserId);
        newsChildComment.setComment(comment);
        newsChildCommentMapper.insert(newsChildComment);

        int childCommentId = newsChildComment.getId();

        apiResponse = new ApiResponse<>(ResponseCode.SUCCESS, "请求成功", childCommentId);
        return apiResponse;
    }

    @Override
    public ApiResponse<Object> supportComment(Integer commentId, Integer userId) {
        // 查询对应关系是否已存在
        NewsCommentSupport newsCommentSupport = newsCommentSupportMapper
                .selectOne(new QueryWrapper<NewsCommentSupport>()
                        .eq("news_comment_id", commentId)
                        .eq("user_id", userId));
        if (newsCommentSupport == null) {
            // 若关系记录不存在，说明是未点赞状态，新建关系类并将记录插入关系表
            NewsCommentSupport newsCommentSupport1 = new NewsCommentSupport();
            newsCommentSupport1.setNewsCommentId(commentId);
            newsCommentSupport1.setUserId(userId);
            newsCommentSupportMapper.insert(newsCommentSupport1);

            apiResponse = new ApiResponse<>(ResponseCode.SUCCESS, "请求成功", "点赞评论成功");
        } else {
            // 若关系记录存在，说明是已点赞状态，相当于执行取消点赞的操作，删除对应关系记录
            newsCommentSupportMapper.deleteById(newsCommentSupport.getId());

            apiResponse = new ApiResponse<>(ResponseCode.SUCCESS, "请求成功", "取消点赞评论");
        }
        return apiResponse;
    }

    @Override
    public ApiResponse<Object> supportChildComment(Integer childCommentId, Integer userId) {
        // 业务逻辑与supportComment方法相同
        NewsChildCommentSupport newsChildCommentSupport = newsChildCommentSupportMapper
                .selectOne(new QueryWrapper<NewsChildCommentSupport>()
                        .eq("news_child_comment_id", childCommentId)
                        .eq("user_id", userId));
        if (newsChildCommentSupport == null) {
            NewsChildCommentSupport newsChildCommentSupport1 = new NewsChildCommentSupport();
            newsChildCommentSupport1.setNewsChildCommentId(childCommentId);
            newsChildCommentSupport1.setUserId(userId);
            newsChildCommentSupportMapper.insert(newsChildCommentSupport1);

            apiResponse = new ApiResponse<>(ResponseCode.SUCCESS, "请求成功", "点赞回复成功");
        } else {
            newsChildCommentSupportMapper.deleteById(newsChildCommentSupport.getId());

            apiResponse = new ApiResponse<>(ResponseCode.SUCCESS, "请求成功", "取消点赞回复");
        }
        return apiResponse;
    }
}
